
#include "clog.h"
#include "def_ver.h"


CLog *CLog::_log = 0;
i32 errcode1 = 0;

//extern int build_ver;

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


CLog::CLog()
{
    _status = 0;
    _min_prior = 10;
    _tabs = 0;
    _log = this;
    _function_tree = 1;
    _console_out = 1;
}


CLog::~CLog()
{
    CloseLog();
}

int CLog::Create()
{
    new CLog;
    return 1;
};

int CLog::Destroy()
{
    delete _log;
    return 1;
}


int CLog::StartLog ( string file_name, uint32_t mode )
{
    char str_mode[10];
    if ( mode == MOD_APPEND )
        strcpy ( str_mode, "a" );
    else
        strcpy ( str_mode, "w" );
    _file = fopen ( file_name.c_str(), str_mode );
    if ( !_file )
    {
        _file = fopen ( "log-secondary.log", "w" );
        if ( !_file )
        {
            printf ( " Can't create log file.[ %d ]", errno );
            _status = 0;        // mean not opened.
            return 0;
        }
    }
    _status = 1;        // mean ok.
    WriteHeader();
    return 1;
}

int CLog::CloseLog()
{
    WriteEndMsg();
    fclose ( _file );
    _file = 0;
    _status = 0;
    return 1;
}

int CLog::SetMinPriority ( uint32_t priority )
{
    _min_prior = priority;
    return 1;
}

int CLog::Print ( uint32_t prior, char *fmt, ... )
{

    pthread_mutex_lock( & mutex );

    va_list args;
    va_start ( args, fmt );
    static char buff[8192];
    static char buf2[8192];
    static char buft[256];
    TimeToStr(buft);
    sprintf ( buf2, "%d" ,prior );
    vsnprintf ( buff, 8192, fmt, args );
    strcat ( buf2, "<" );
    strcat ( buf2, buft );
    strcat ( buf2, ">" );
    strcat ( buf2, buff );
    WriteBuffer ( buf2, prior );

    pthread_mutex_unlock( & mutex );

    // TODO : put buffer into right place !
    return 1;
}

int CLog::Print (  char *fmt, ... )
{
    pthread_mutex_lock( & mutex );


    va_list args;
    va_start ( args, fmt );
    static char buff[8192];
    static char buf2[8192];
    static char buft[256];
    strcpy(buf2,"0");
    TimeToStr(buft);
    vsnprintf ( buff, 8192, fmt, args );
    strcat ( buf2, "<" );
    strcat ( buf2, buft );
    strcat ( buf2, ">" );
    strcat ( buf2, buff );
    WriteBuffer ( buf2, 0 );

    pthread_mutex_unlock( & mutex );


    // TODO : put buffer into right place !
    return 1;
}

int CLog::WriteHeader ( string prog_name, string prog_author, uint32_t major_ver,
                        uint32_t minor_ver, uint32_t rev  )
{
    pthread_mutex_lock( & mutex );

    char buff[2048];
    sprintf ( buff, "\n\n\n===================================================" );
    WriteBuffer ( buff );
    sprintf ( buff, "%s(%s)  by %s v%d.%d rev %d ", VER_APPNAME,VER_MINNAME, VER_AUTHOR, VER_MAJOR, VER_MINOR, VER_REV );
    WriteBuffer ( buff );
    sprintf ( buff, "TIME : %s", DateToString().c_str() );
    WriteBuffer ( buff );
    sprintf ( buff, "===================  START LOG  ===================" );
    WriteBuffer ( buff );
    pthread_mutex_unlock( & mutex );

    return 1;
}

int CLog::WriteEndMsg()
{
    pthread_mutex_lock( & mutex );

    char buff[2048];
    sprintf ( buff, "===================================================" );
    WriteBuffer ( buff );
    sprintf ( buff, "TIME : %s", DateToString().c_str() );
    WriteBuffer ( buff );
    sprintf ( buff, "===================   END LOG   ===================" );
    WriteBuffer ( buff );
    pthread_mutex_unlock( & mutex );

    return 1;
}

void CLog::TimeToStr(char *buffer)
{
    time_t rawtime;
    struct tm * timeinfo;

    time ( &rawtime );
    timeinfo = localtime ( &rawtime );

    strftime (buffer,80,"%H:%M:%S",timeinfo);

}


int CLog::WriteBuffer ( char *buff , uint32_t prior )
{
    ////
    if (!_status)
    {
        printf("\nLOG Closed ?\n");
        return 0;
    }
    if ( !_status || prior > _min_prior )
        return 0;
    strcat ( buff, "\n" );
    uint32_t ret_code = fwrite ( buff, sizeof ( char ), strlen ( buff ), _file );
    if (_console_out)
    {
        printf("%s",buff);
    }
    if ( ret_code != strlen ( buff ) )
    {
        printf ( "Error on writing to the stream. [%d]\n", errno );
        return 0;
    }
    fflush(_file);
    return 1;
}

string CLog::DateToString()
{
    time_t cur_time;
    time ( &cur_time );
    string str_time = ctime ( &cur_time );
    str_time.erase ( str_time.length() - 1 );
    return str_time;
}

int CLog::Stampin ( char *func_name )
{
    if ( !_log->_function_tree )
        return 0;
    static char buff[2048];
    uint32_t c;
    for ( c = 0; c < _log->_tabs; c++ )
    {
        buff[c] = 9;
    }
    buff[c] = '\0';
    strcat ( buff, "IN :" );
    strcat ( buff, func_name );
    _log->WriteBuffer ( buff, 0 );
    _log->_tabs++;
    return 1;
}

int CLog::Stampout ( char *func_name )
{
    if ( !_log->_function_tree )
        return 0;
    if ( _log->_tabs > 0 )
        _log->_tabs--;
    static char buff[2048];
    uint32_t c;
    for ( c = 0; c < _log->_tabs; c++ )
    {
        buff[c] = 9;
    }
    buff[c] = '\0';
    strcat ( buff, "OUT:" );
    strcat ( buff, func_name );
    _log->WriteBuffer ( buff, 0 );
    return 1;
}


//int Mark ( char *file, char *func_name, uint32_t line );


//////////////////////////////////
